package com.example.simplesvc;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedByInterruptException;
import java.nio.channels.SocketChannel;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class MyOutOfSpringServiceWithExecutor implements MyServerStopListener {


    private static Logger log = LoggerFactory.getLogger(MyOutOfSpringServiceWithExecutor.class);

    private ThreadPoolExecutor pool = new ThreadPoolExecutor(10, 10, 1, TimeUnit.MINUTES, new ArrayBlockingQueue<>(1024));


    public MyOutOfSpringServiceWithExecutor() {
        //注册到MyServerStopListenerRegister ，待tomcat受到关闭命令时会回调 onServerStopping 接口
        MyServerStopListenerRegister.getInstance()
                .registerListener(this);
    }

    public void runSimpleTask() {
        pool.execute(new Runnable() {
            @Override
            public void run() {
                for (; ; ) {
                    log.info("mock a forever task processing biz");

                    //1 sleep，wait，join等操作 可能会引起因为中断引起 InterruptedException
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        log.info("线程被中断，退出执行");
                        return;
                    }

                    //2 InterruptibleChannel 网络通信操作，可能会引起因为中断引起 ClosedByInterruptException
                    try {
                        InetSocketAddress addr = new InetSocketAddress("www.163.com", 80);
                        //建立连接时可如果线程被中断，就会抛出ClosedByInterruptException
                        SocketChannel ch = SocketChannel.open(addr);
                        ByteBuffer bb = ByteBuffer.allocate(4096);
                        //读取数据时可如果线程被中断，就会抛出ClosedByInterruptException
                        ch.read(bb);
                        bb.flip();
                        log.info("received data " + new String(bb.array()));
                    } catch (ClosedByInterruptException e) {
                        log.info("线程被中断，退出执行");
                        return;
                    } catch (Exception e) {
                        log.error("通信失败", e);
                    }


                    //3 检查线程状态，若处于中断状态，退出执行
                    if (Thread.currentThread().isInterrupted()) {
                        log.info("线程被中断，退出执行");
                        return;
                    }
                }
            }
        });
    }

    @Override
    public void onServerStopping() {
        try {
            shutdownExecutor();
        } catch (Exception e) {
            log.warn("关闭executor失败", e);
        }
    }


    private void shutdownExecutor() {
        pool.shutdown(); // 停止新任务提交
        try {
            // 等正在执行的任务执行完毕
            if (!pool.awaitTermination(10, TimeUnit.SECONDS)) {
                pool.shutdownNow(); // 取消当前正在执行的任务
                //等待任务取消
                if (!pool.awaitTermination(10, TimeUnit.SECONDS)) {
                    log.warn("Pool did not terminate");
                }
            }
        } catch (InterruptedException ie) {
            // 若当前线程在等待结束是被打断，重新取消正在执行的任务
            pool.shutdownNow();
            // Preserventerrupt status
            Thread.currentThread().interrupt();
        }
    }
}
